//package projects.part5;

import info.gridworld.grid.AbstractGrid;
import info.gridworld.grid.Location;

import java.util.ArrayList;

public class UnboundedGrid2<E> extends AbstractGrid<E> {
    private Object[][] occArray;
    private int dimension;

    public UnboundedGrid2() {
        dimension = 16;
        occArray = new Object[dimension][dimension];
    }

    @Override
    public int getNumRows() {
        return -1;
    }

    @Override
    public int getNumCols() {
        return -1;
    }

    @Override
    public boolean isValid(Location loc) {
        int r = loc.getRow();
        int c = loc.getCol();
        return ((r>=0)&&(c>=0));
    }

    @Override
    public E put(Location loc, E obj) {
        if (loc == null) {
            throw new IllegalArgumentException("Error! Location: " + loc + " is InValid.");
        }
        if (obj == null) {
            throw new IllegalArgumentException("Error! obj == null");
        }

        int r = loc.getRow();
        int c = loc.getCol();

        if (r >= dimension || c >= dimension) {
            resize(loc);
        }

        E old = get(loc);
        occArray [r][c] = obj;
        return old;
    }

    private void resize(Location loc) {
        int size = dimension;
        while (loc.getRow() >= size || loc.getCol() >= size) {
            size *= 2;
        }
        Object[][] newArray = new Object[size][size];

        for (int r = 0; r < dimension; r++) {
            for (int c = 0; c < dimension; c++) {
                newArray[r][c] = occArray[r][c];
            }
        }
        occArray = newArray;
        dimension = size;
    }

    @Override
    public E remove(Location loc) {
        if (!isValid(loc)) {
            throw new IllegalArgumentException("Error! Location: " + loc + " is InValid.");
        }
        int r = loc.getRow();
        int c = loc.getCol();
        if (r >= dimension || c >= dimension) {
            return null;
        }
        E old = get(loc);
        occArray[r][c] = null;
        return old;
    }

    @Override
    public E get(Location loc) {
        if (!isValid(loc)) {
            throw new IllegalArgumentException("Error! Location: " + loc + " is InValid.");
        }
        int r = loc.getRow();
        int c = loc.getCol();
        if (r >= dimension || c >= dimension) {
            return null;
        }
        return (E)occArray[r][c];
    }

    @Override
    public ArrayList<Location> getOccupiedLocations() {
        ArrayList<Location> res = new ArrayList<Location>();
        for (int r = 0; r < dimension; r++) {
            for (int c = 0; c < dimension; c++) {
                Location loc = new Location(r,c);
                if (get(loc) != null) {
                    res.add(loc);
                }
            }
        }
        return res;
    }
}
